Some computer system environments allow data from one application to be integrated with data from another application in such a way that all of the data appears to a user to be managed by one application. The data belonging to the application providing a containment environment for all of the data is typically referred to as native data. The containment environment is typically referred to as a container and the application responsible for providing and managing the container is typically referred to as a container application or container program. The data being incorporated into the native data that is generated by and managed using another application is typically referred to as non-native data. Users can embed non-native data within the native data of a container application by inserting the non-native data into the storage structure of the container application. Or, users can link non-native data into the native data of a container application by storing an indicator to the non-native data in the storage facilities of the container application. When embedded or linked, such non-native data is referred to as source data and the program used to manipulate the source data is referred to as the server program. Consequently, the container program is also referred to as a client program because it is a client of the source data maintained by the server program.
For example, a user may wish to create a document using a word processing application containing a chart created by a spreadsheet application. Such a document is sometimes referred to as a compound document. FIG. 1 is an example of a compound document. In this example, the compound document 101 is generated as a report for a certain manufacturing project. The compound document 101 contains scheduling data 102, which is presented in chart format; budgeting data 103, which is presented in spreadsheet format; and explanatory data 104, which is presented in text format. In typical prior systems, a user generates the scheduling data 102 and the budgeting data 103 using a spreadsheet computer program. After this data has been generated, the user creates the compound document 101, enters the explanatory data 104, and incorporates the scheduling data 102 and budgeting data 103 using a word processing computer program. In this example, the explanatory data 104 is native data to the word processing computer program, and the scheduling data 102 and budgeting data 103 is non-native data (source data) contained within a compound document (a container).
Within an environment such as that shown in FIG. 1, where the linking or embedding of non-native data is supported, often times the container program desires to display the non-native data as well as the native data. However, the container program (the client program) does not understand the non-native data because it was created by and is managed by the server program. Thus, in prior systems that use conventional architectures, the non-native data is typically stored by the client program in a presentation format so that it can be displayed by the client program. A presentation format is a format in which the data can be easily displayed on an output device. For example, the presentation format may be a bitmap that can be displayed with a standard bitmap block transfer operation (BITBLT). (For example, in FIG. 1 the scheduling data 102 and budgeting data 103 may be stored by the word processing program as bitmaps, or in other formats, when they are embedded in compound document 101.) Alternatively, if the non-native data is linked by the client program, then the client program typically stores a link to the source data that has been formatted in a format that the client program can treat as a presentation format. In these prior systems, when the client program wishes to display the non-native data using conventional programming style, it renders (places appropriately on a particular output device) the non-native data stored according to the presentation format. Data stored according to a presentation format is sometimes referred to as presentation data.
If the client program desires to display the non-native data in a format different from that which it has stored (or has access to via a link), then the client program can request the data again from the server program but in a different presentation format. For example, a client program may wish the data in another presentation format to print the native and non-native data together in a paginated format. The client program can then render the data in the new presentation format received from the server program. Requesting the data again from the server program requires the server program to be reloaded and re-executed.
Also, in prior systems that support an object-oriented environment, if the non-native data belongs to an object (objects are discussed further below), then the client program typically invokes a function member of the object requesting the object to draw itself in a particular location or context. Note that this latter technique gives the client program little control over how the object renders the object's data.
The present invention is described below using some object-oriented techniques; thus, an overview of well-known object-oriented programming techniques is provided. Two common characteristics of object-oriented programming languages are support for data encapsulation and data type inheritance. Data encapsulation refers to the binding of functions and data. Inheritance refers to the ability to declare a data type in terms of other data types. In the C++ language, data encapsulation and inheritance are supported through the use of classes. A class is a user-defined type. A class declaration describes the data members and function members of the class. A function member is also referred to as a method of a class. The data members and function members of a class are bound together in that the function operates on an instance of the class. An instance of a class is also called an object of the class. Thus, a class provides a definition for a group of objects with similar properties and common behavior.
To allocate storage for an object of a particular type (class), an object is instantiated. Once instantiated, data can be assigned to the data members of the particular object. Also, once instantiated, the function members of the particular object can be invoked to access and manipulate the data members. Thus, in this manner, the function members implement the behavior of the object, and the object provides a structure for encapsulating data and behavior into a single entity.
To support the concept of inheritance, classes may be derived from (based upon the declaration of) other classes. A derived class is a class that inherits the characteristics—data members and function members—of its base classes. A class that inherits the characteristics of another class is a derived class. A class that does not inherit the characteristics of another class is a primary (root) class. A class whose characteristics are inherited by another class is a base class. A derived class may inherit the characteristics of several classes; that is, a derived class may have several base classes. This is referred to as multiple inheritance.
A class may also specify whether its function members are virtual. Declaring that a function member is virtual means that the function can be overridden by a function of the same name and type in a derived class. If a virtual function is declared without providing an implementation, then it is referred to as a pure virtual function. A pure virtual function is a virtual function declared with the pure specifier, “=0”. If a class specifies a pure virtual function, then any derived class needs to specify an implementation for that function member before that function member may be invoked. A class which contains at least one pure virtual function member is an abstract class.
FIG. 2 is a block diagram illustrating typical data structures used to represent an object. An object is composed of instance data (data members) and function members, which implement the behavior of the object. The data structures used to represent an object comprise instance data structure 201, virtual function table 202, and the function members 203, 204, 205. The instance data structure 201 contains a pointer to the virtual function table 202 and contains data members. The virtual function table 202 contains an entry for each virtual function member defined for the object. Each entry contains a reference to the code that implements the corresponding function member. The layout of this sample object conforms to models described in U.S. Pat. No. 5,297,284, entitled “A Method for Implementing Virtual Functions and Virtual Bases in a Compiler for an Object Oriented Programming Language,” which is hereby incorporated by reference. One skilled in the art would appreciate that other object models can be defined using programming languages other than the C++programming language.
An advantage of using object-oriented techniques is that these techniques can be used to facilitate the sharing of objects. For example, a program implementing the function members of an instantiated object (the server program) can share the object with another program (the client program). To allow an object of an arbitrary class to be shared with a client program, interfaces are defined through which an object can be accessed without the need for the client program to have access to the class definitions at compile time. An interface is a named set of logically related function members. In C++, an interface is an abstract class with no data members and whose virtual functions are all pure. Thus, an interface provides a published protocol for two programs to communicate. Interfaces are typically used for derivation: a program defines (implements) classes that provide implementations for the interfaces the classes are derived from. Thereafter, objects are created as instances of these derived classes. Objects instantiated from a derived class implementing particular interfaces are said to “support” the interfaces. An object supports one or more interfaces depending upon the desired functionality.
When a client program desires to share an object, the client program needs access to the code that implements the interfaces for the object (the derived class code). To access the derived class code (also referred to as class code), each class implementation is given a unique class identifier (a “CLSID”). For example, code implementing a spreadsheet object developed by Microsoft Corporation may have a class identifier of “MSSpreadsheet,” while code implementing a spreadsheet object developed by another corporation may have a class identifier of “LTSSpreadsheet.” A persistent registry in each computer system is maintained that maps each CLSID to the code that implements the class. Typically, when a spreadsheet program is installed on a computer system, the persistent registry is updated to reflect the availability of that class of spreadsheet objects. So long as a spreadsheet developer implements each function member defined by the interfaces to be supported by spreadsheet objects and so long as the persistent registry is maintained, the client program can access the function members of shared spreadsheet objects without regard to which server program has implemented them or how they have been implemented.
Since an object may support some interfaces and not others, a client program would need to determine at runtime whether a particular object supports a particular interface. To enable this determination, every object preferably supports the interface IUnknown, which contains a function member, QueryInterface, that indicates which interfaces are implemented for the object. The method QueryInterface is defined as follows:virtual HRESULT QueryInterface (REFIID iid, void**ppv)=0;The method QueryInterface is passed an interface identifier in parameter iid (of type REFIID) and returns in parameter ppv a pointer to the implementation of the requested interface of the object for which the method is invoked. If the object does not support the interface, then the method returns an indication that the requested interface is not supported. The type HRESULT indicates a return status predefined by the object-oriented environment.
FIG. 3 is a symbolic representation of an object. In the following description, an object data structure is represented by the shape 301 labeled with the interfaces through which the object may be accessed. As shown, object 301 supports IInterface1 and IInterface2.